﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using RobotGerchik.DataClass.Gerchik;
using RobotGerchik.Views;
using System.IO;
using RobotGerchik.DataClass;
using RobotGerchik.Views.Dialogs;
using RobotGerchik.Config;
using System.Diagnostics;
using System.Windows.Threading;
using System.Collections.ObjectModel;
using RobotGerchik.DataClass.BaseTransaqCalss;
using System.Text.RegularExpressions;

namespace RobotGerchik
{

    delegate void NewDataHandler(string data);
    /// RobotGerchiksummary>
    /// Логика взаимодействия для MainWindow.xaml
    /// RobotGerchik/summary>
    public partial class MainWindow : Window
    {
        public static string Password;
        public static string Login;

        public string AppDir; // путь к папке приложения
        public static bool BConnecting; // флаг процесса подключения к серверу
        public static bool BDisconnecting; // флаг процесса отключения от сервера
        public static bool BConnected; // флаг наличия подключения к серверу

        public TXmlConnector OConn; // коннектор

        private event NewDataHandler OnNewDataEvent;

        public bool LogFlag = true; // флаг записи лог-файла
        public StreamWriter LogFile; // переменная лог-файла
        public char PointChar; // символ для замены точки в числах
        public List<string> ColInstrumentSubscribe; //коллекция инструментов, на которые подписаны
        public ObservableCollection<HistoryItems> DictionaryHistoryData; // словарь по истории получаемых данных (период/ бумага)
        public List<int> TicksListInstruments; //Лист инструментов необходимых для получении истории

        public Data DataProvider = new Data();

        History history;
        private DispatcherTimer timer;
        ShowMassege method;

        public MainWindow()
        {


            // определение папки, в которой запущена программа
            string path = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + "\\RobotGerchik\\";
            AppDir = path;
            ColInstrumentSubscribe = new List<string>();
            DictionaryHistoryData = new ObservableCollection<HistoryItems>();
            TicksListInstruments = new List<int>();

            InitializeComponent();

            // открытие лог-файла
            if (LogFlag)
            {
                if (!Directory.Exists(path))
                {
                    System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path);
                    dir.Create();
                }
                path = AppDir + "log.txt";
                if (File.Exists(path)) File.Delete(path);
                File.Create(path).Close();
                LogFile = File.AppendText(path);
                WriteLog("START LOGGING");
            }

            // определение разделителя в числах на компьютере (запятая или точка)
            //PointChar = ',';
            //string str = (1.2).ToString();
            //if (str.IndexOf('.') > 0) PointChar = '.';
            DictionaryMarkets = new Dictionary<int, string>();
            DictionaryTimeFrame = new Dictionary<int, string>();

            OConn = new TXmlConnector();

            string logPath = AppDir + "\0";
            string resStr = OConn.ConnectorInitialize(logPath, 3);

            OConn.NewData += new EventHandler<TXmlConnector.NewDataEventArgs>(OnNewDataConnector);

            this.OnNewDataEvent += new NewDataHandler(OnNewData);
            history = new History(DataProvider);
            history.Load();
            //Привязываем таблицы
            dtgdSecurities.ItemsSource = DataProvider.SecuritiesList;
            dtgdRobotGerchik.ItemsSource = DataProvider.GechikRobotItemList;
            dtgdHistory.ItemsSource = DataProvider.CandlesItems;

            dtgdOrders.ItemsSource = DataProvider.OrderList;
            dtgdStopOrders.ItemsSource = DataProvider.StopOrderList;
            dtgdDeals.ItemsSource = DataProvider.DealList;

            dtgdSecposition.ItemsSource = DataProvider.SecPositionList;
            dtgdMoneyPosition.ItemsSource = DataProvider.MoneyPositionList;


            timer = new DispatcherTimer();
            timer.Interval = new TimeSpan(1000);
            timer.Start();
            timer.Tick += new EventHandler(Timer_Tick);


            method = RobotLog;
            //history.Load();
        }




        private void OnNewDataConnector(object sender, TXmlConnector.NewDataEventArgs e)
        {
            //Этот метод вызывается при получении новых данных
            //this.onNewDataEvent += new NewDataHandler(OnNewData)
            this.Dispatcher.Invoke(OnNewDataEvent, new object[] { e.data }); //чтобы не было проблем с отображением
        }

        private void OnNewData(string data)
        {
            Transaq_HandleData(data);
        }



        private void MenuItem_SaveSettings_Click(object sender, RoutedEventArgs e)
        {
            history.Save();
        }

        private void MenuItem_LogFolder_Click(object sender, RoutedEventArgs e)
        {
            String path = Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + "\\RobotGerchik\\";
            if (Directory.Exists(path))
                Process.Start("explorer", path);
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            Connecting();
        }

        void Transaq_Disconnect()
        {
            // отключение коннектора от сервера Транзак
            BConnected = false;
            BConnecting = false;
            BDisconnecting = true;

            Transaq_Reflect();

            string cmd = DataProvider.TransaqCommand.Disconnect();

            WriteLog("SendCommand: " + cmd);
            string res = OConn.SendCommand(cmd);
            WriteLog("ServerReply: " + res);

            Transaq_Reflect();
        }

        public void RobotLog(string str)
        {
            lsbxRobotLog.Items.Add(str);
        }

        public void WriteLog(string logStr)
        {
            if (LogFlag)
            {
                LogFile.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + " " + logStr);
                LogFile.Flush();
            }
        }

        void Transaq_Reflect()
        {
            // отображение состояния подключения на форме
            string status = "offline";
            string button = "Подключить";
            btnConnect.IsEnabled = true;
            btnDisconnect.IsEnabled = false;
            MenuItem_RunConnect.IsEnabled = true;
            MenuItem_RunDisconnect.IsEnabled = false;
            string msg = "";

            if (BConnected)
            {
                status = "online";
                btnConnect.IsEnabled = false;
                btnDisconnect.IsEnabled = true;
                MenuItem_RunConnect.IsEnabled = false;
                MenuItem_RunDisconnect.IsEnabled = true;

            }
            else
            {
                if (BConnecting)
                {
                    status = "connect";
                    button = "Подключаю";
                    msg = "Подключение к серверу...";
                }
                if (BDisconnecting)
                {
                    status = "disconn";
                    button = "Отключаю";
                    msg = "Отключение от сервера...";
                }
            }


            if (msg.Length > 0) ShowStatus(msg);
        }

        void Transaq_Connect()
        {
            // подключение коннектора к серверу Транзак
            BConnected = false;
            BConnecting = true;
            BDisconnecting = false;

            if (String.IsNullOrEmpty((Password)))
                Password = "n5GN3s";
            if (String.IsNullOrEmpty((Login)))
                Login = "TCNN9966";

            // проверка наличия параметров
            if (String.IsNullOrEmpty(Login))
            {
                ShowStatus("Не указан логин");
                return;
            }
            if (String.IsNullOrEmpty(Password))
            {
                ShowStatus("Не указан пароль");
                return;
            }
            if (String.IsNullOrEmpty(Properties.Settings.Default.IPadress))
            {
                ShowStatus("Не указан IP-адрес");
                return;
            }
            if (String.IsNullOrEmpty(Properties.Settings.Default.Port))
            {
                ShowStatus("Не указан порт");
                return;
            }

            Transaq_Reflect();


            // формирование текста команды
            string cmd = "<command id=\"connect\">";
            cmd = cmd + "<login>" + Login + "</login>";
            cmd = cmd + "<password>" + Password + "</password>";
            cmd = cmd + "<host>" + Properties.Settings.Default.IPadress + "</host>";
            cmd = cmd + "<port>" + Properties.Settings.Default.Port + "</port>";
            cmd = cmd + "<logsdir>" + AppDir + "</logsdir>";
            cmd = cmd + "<micex_registers>true</micex_registers>";
            cmd += "<rqdelay>330</rqdelay>";
            cmd = cmd + "</command>";

            // отправка команды
            WriteLog("SendCommand: <command id=\"connect\"><login>" + Login + "</login><password>*</password><host>" + Properties.Settings.Default.IPadress + "</host><port>" + Properties.Settings.Default.Port + "</port><logsdir>" + AppDir + "</logsdir><rqdelay>330</rqdelay></command>");
            string res = OConn.SendCommand(cmd);
            WriteLog("ServerReply: " + res);

            Transaq_Reflect();
        }

        public void ShowStatus(string statusStr)
        {
            // вывод сообщения в строке статуса формы
            txt_Status.Text = statusStr;
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        private void CreateNewDocument(object sender, RoutedEventArgs e)
        {

        }

        private void Button_AddRow_Click(object sender, RoutedEventArgs e)
        {
            GechikRobotItem item = new GechikRobotItem();
            addNewGerchikRobot ngr = new addNewGerchikRobot(item, DataProvider, false);
            ngr.ShowDialog();

            if (item.ClientCode != null)
            {
                if (item.TradeList == null)
                    item.TradeList = new ObservableCollection<TradesOpen>();
                DataProvider.GechikRobotItemList.Add(item);
            }
        }

        private void dtgdRobotGerchik_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            for (int i = 0; i < DataProvider.GechikRobotItemList.Count; i++)
            {
                if (((DataGrid)sender).SelectedIndex == i)
                    dtgdOrder.ItemsSource = DataProvider.GechikRobotItemList[i].TradeList;
            }
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {

        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {

        }

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {

        }

        private void CheckBox_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < DataProvider.GechikRobotItemList.Count; i++)
            {
                DataProvider.GechikRobotItemList[i].Check = (sender as CheckBox).IsChecked.Value;
            }
            dtgdRobotGerchik.ItemsSource = DataProvider.GechikRobotItemList;
        }

        private void btnClearData_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < DataProvider.GechikRobotItemList.Count; i++)
            {
                if (DataProvider.GechikRobotItemList[i].Check)
                    DataProvider.GechikRobotItemList[i].TradeList.Clear();
            }
        }

        private void btnConnect_Click(object sender, RoutedEventArgs e)
        {
            Connecting();
        }

        private void Connecting()
        {
            Connect connect = new Connect();
            connect.ShowDialog();


            // нажата кнопка подключения
            if (connect.DialogResult == true)
                if (BConnected || BConnecting)
                {
                    Transaq_Disconnect();
                }
                else
                {
                    if (!BConnecting) Transaq_Connect();
                }
        }

        private void btnDisconnect_Click(object sender, RoutedEventArgs e)
        {
            Disconnect();
        }

        private void Disconnect()
        {
            if (BConnected || BConnecting)
            {
                Transaq_Disconnect();
            }
            else
            {
                if (!BConnecting) Transaq_Connect();
            }
        }

        private void BtnMenuItemDisconnect(object sender, RoutedEventArgs e)
        {
            Disconnect();
        }

        private void dtgdSecurities_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // формирование текста команды
            //string cmd = "<command id=\"subscribe\">";
            //cmd = cmd + "<quotations>";
            //cmd = cmd + "<secid>" + ((Securities)(((DataGrid)sender).SelectedItem)).Secid + "</secid>";
            //cmd = cmd + "</quotations>";
            //cmd = cmd + "</command>";

            // отправка команды
            // WriteLog("SendCommand: <command id=\"connect\"><login>" + Login + "</login><password>*</password><host>" + Properties.Settings.Default.IPadress + "</host><port>" + Properties.Settings.Default.Port + "</port><logsdir>" + AppDir + "</logsdir><rqdelay>330</rqdelay></command>");

        }

        private void btnCopy_Click(object sender, RoutedEventArgs e)
        {
            if (dtgdRobotGerchik.SelectedItems.Count == 1)
            {
                int index = dtgdRobotGerchik.SelectedIndex + 1;
                dtgdRobotGerchik.UnselectAll();
                try
                {
                    if (new DialogOkCancel("Вы действительно хотите скопировать строку " + index + "?", "Внимание").Result == MessageBoxResult.OK)
                    {
                        var tmp = (GechikRobotItem)Cfg.DeepClone(DataProvider.GechikRobotItemList[index - 1 < 0 ? 0 : index - 1]);
                        if (tmp.IsRun == false)
                            DataProvider.GechikRobotItemList.Add(tmp);
                        else
                            new DialogOkCancel("Для продолжения копирования нужно остановить копируемю строку", "Ошибка");
                    }
                }
                catch
                { }
            }
        }

        private void dtgdRobotGerchik_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (dtgdRobotGerchik.SelectedIndex >= 0)
            {
                GechikRobotItem grItem = ((DataGrid)sender).SelectedItem as GechikRobotItem;
                addNewGerchikRobot ngr = new addNewGerchikRobot(grItem, DataProvider, true);
                ngr.ShowDialog();
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            {
                if ((new DialogYesNo("Вы действительно хотите выйти?", "Внимание!")).Result == MessageBoxResult.Yes)
                {
                    if ((new DialogYesNo("Сохранить данные?", "Внимание!")).Result == MessageBoxResult.Yes)
                    {
                        history.Save();
                    }
                }
                else
                    e.Cancel = true;
            }
        }

        /// <summary>
        /// Удаление всех выделенных роботов.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDelete_Click(object sender, RoutedEventArgs e)
        {
            for (int j = 0; j < DataProvider.GechikRobotItemList.Count; j++)
            {
                if (DataProvider.GechikRobotItemList[j].Check == true)
                {
                    DataProvider.GechikRobotItemList.RemoveAt(j);
                    j--;
                }
            }
        }


        /// <summary>
        /// Подписка на получение данных
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Timer_Tick(object sender, EventArgs e)
        {
            if (BConnected == true)
            {
                HistoryItems newHistoryItems = new HistoryItems();
                if (DataProvider.GechikRobotItemList.Count > 0)
                {
                    foreach (var item in DataProvider.GechikRobotItemList)
                    {
                        if (!ColInstrumentSubscribe.Contains(item.Instrument) && item.IsRun == true)
                        {
                            if (DataProvider.SecuritiesList.Count > 0)
                                foreach (var item2 in DataProvider.SecuritiesList)
                                {
                                    if (item2.Seccode == item.Instrument)
                                    {
                                        string res = OConn.SendCommand(DataProvider.TransaqCommand.SubscribeQuotations(item2.Secid));
                                        ColInstrumentSubscribe.Add(item.Instrument);
                                        WriteLog("ServerReply: " + res);
                                        List<int> list = new List<int>();
                                        list.Add(item2.Secid);
                                        res = OConn.SendCommand(DataProvider.TransaqCommand.SubscribeTick(list));
                                        WriteLog("ServerReply: " + res);
                                    }
                                }

                        }

                        //Получение данных по истори
                        if (DictionaryHistoryData.Where(a => a.Seccode == item.Instrument).
                            Where(a => a.TimeFrame == DictionaryTimeFrame.FirstOrDefault(x => x.Value == item.TimeFrame).Key).ToList().Count == 0

                            && item.IsRun == true)
                        {
                            if (DataProvider.SecuritiesList.Count > 0)
                                foreach (var item2 in DataProvider.SecuritiesList)
                                {

                                    if (item2.Seccode == item.Instrument)
                                    {
                                        if (!TicksListInstruments.Contains(item2.Secid))
                                        {
                                            TicksListInstruments.Add(item2.Secid);
                                            string result = OConn.SendCommand(DataProvider.TransaqCommand.SubscribeTick(TicksListInstruments));
                                            WriteLog("ServerReply: " + result);
                                        }

                                        string res = OConn.SendCommand(DataProvider.TransaqCommand.GetHistoryDateBoardSeccode
                                            (item2.Board, item.Instrument, DictionaryTimeFrame.FirstOrDefault(x => x.Value == item.TimeFrame).Key, 100, "true"));
                                        WriteLog("ServerReply: " + res);
                                        DictionaryHistoryData.Add(new HistoryItems() { Seccode = item.Instrument, TimeFrame = DictionaryTimeFrame.FirstOrDefault(x => x.Value == item.TimeFrame).Key });
                                        WriteLog("ServerReply: " + res);
                                    }
                                }

                        }

                    }
                }

                if (DataProvider.GechikRobotItemList.Count > 0)
                {
                    foreach (var item in DataProvider.GechikRobotItemList)
                    {
                        if (item.IsRun == true)
                        {
                            LogikGerchikRobot logik = new LogikGerchikRobot(DataProvider, this, method);
                            logik.Start(item);
                        }
                    }

                }
            }
        }

        private void dtgdHistory_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            for (int i = 0; i < DataProvider.CandlesItems.Count; i++)
            {
                if (((DataGrid)sender).SelectedIndex == i)
                    dtgdHistoryCandle.ItemsSource = DataProvider.CandlesItems[i].Candle;
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {

            var item = ((Securities)(dtgdSecurities.SelectedItem));
            var dfdf = DataProvider.TransaqCommand.NewOrderBoardSeccode(false, true, item.Secid, item.Board, item.Seccode, DataProvider.GetClientCode()[0], 1, 2035, 'B', "");
            var dffff = OConn.SendCommand(dfdf);
        }

        private void btnCancelAll_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < DataProvider.GechikRobotItemList.Count; i++)
            {
                if (DataProvider.GechikRobotItemList[i].Check)
                {
                    var orderMassiv = DataProvider.GetOrderListAllforInstrunemtsActive(DataProvider.GechikRobotItemList[i].Account, DataProvider.GechikRobotItemList[i].ClientCode, DataProvider.GechikRobotItemList[i].Instrument);
                    var StopLimitMassiv = DataProvider.GetStopOrderListAllforInstrunemtsActive(DataProvider.GechikRobotItemList[i].Account, DataProvider.GechikRobotItemList[i].ClientCode,
                        DataProvider.GechikRobotItemList[i].Instrument);
                    foreach (var VARIABLE in orderMassiv)
                    {
                        OConn.SendCommand(
                            DataProvider.TransaqCommand.CancelOrder(VARIABLE.Transactionid));
                    }
                    foreach (var VARIABLE in StopLimitMassiv)
                    {
                        OConn.SendCommand(
                     DataProvider.TransaqCommand.CancelStopOrder(VARIABLE.Transactionid));
                    }

                }
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            // Правило: только латинские буквы и цифры, минимум 4, максимум 19
            string passPattern = @"^[a-zA-Z0-9]{4,20}$";

            string oldPass = "TdTuNxRg";
            string newPass = "Der5342noVs";

            string result;
            Match m = Regex.Match(newPass, passPattern);

            if (!BConnected)
            {
                ShowStatus("Для смены пароля подключитесь к серверу");
            }
            //else if (txtNewPass.Text.Length == 0)
            //{
            //    ShowStatus("Введите новый пароль");
            //}
            else if (m.Success)
            {
                string cmd = String.Format("<command id=\"change_pass\" oldpass=\"{0}\" newpass=\"{1}\" />", oldPass, newPass);
                WriteLog("SendCommand: <command id=\"change_pass\" oldpass=\"*\" newpass=\"*\" />");
                result = OConn.SendCommand(cmd);
                WriteLog("ServerReply: " + result);
                ShowStatus(result);
                //XDocument aXmlDoc = XDocument.Load(new System.IO.StringReader(result));
                //if (aXmlDoc.Root.Name == "result")
                //{
                //    if (aXmlDoc.Root.Attribute("success").Value == "true")
                //    {
                //        ShowStatus("Пароль изменен");
                //        WriteLog("Password was changed");
                //        txtOldPass.Text = "";
                //        txtNewPass.Text = "";
                //    }
                //    else if (aXmlDoc.Root.Attribute("success").Value == "false")
                //    {
                //        ShowStatus(aXmlDoc.Root.Value);
                //    }
                //}
                //else
                //{
                //    ShowStatus("Произошла ошибка");
                //}
            }
            else
            {
                ShowStatus("Введите верный новый пароль");
            }
        }


    }

    public class HistoryItems
    {
        private int _timeframe;
        private string _seccode;

        public int TimeFrame { get; set; }
        public string Seccode { get; set; }
    }
}
